package uutalk.netcloud.talk.base.util.thirdpart;

import android.media.AudioFormat;
import android.media.AudioTrack;
import android.util.Log;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.liulishuo.filedownloader.BaseDownloadTask;
import com.liulishuo.filedownloader.FileDownloadSampleListener;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import uutalk.netcloud.talk.base.util.Pcm2Wav;
import uutalk.netcloud.talk.base.mqtt.MQTTManager;
import uutalk.netcloud.talk.base.mqtt.MqttConstant;
import uutalk.netcloud.talk.base.mqtt.PublishFactory;
import uutalk.netcloud.talk.base.mqtt.event.MQTTActionEvent;
import uutalk.netcloud.talk.base.mqtt.event.MqttMessageEvent;
import uutalk.netcloud.talk.base.mqtt.model.Publication;
import uutalk.netcloud.talk.base.util.view.ToastUtil;
import uutalk.netcloud.talk.base.util.FileUtil;
import uutalk.netcloud.talk.model.BussinessBeanFactory;
import uutalk.netcloud.talk.model.bean.CMDConstant;
import uutalk.netcloud.talk.model.bean.DBEntityManager;
import uutalk.netcloud.talk.model.bean.TalkHistoryInfo;

/**
 * Created by hujie on 2018/1/19.
 */

public class PCMManager {


    private static PCMManager INSTANCE;
    private static final String TAG = "PCMManager";

    private AudioTrack player;
    private boolean isPlay;
    private boolean isUploadAll;

    public static PCMManager getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new PCMManager();
        }
        return INSTANCE;
    }

    private PCMManager() {
        if (!EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().register(this);
        }
    }

    /**
     * 启动上传任务
     */
    public void startUploadTask() {
        //每隔10分钟上传一次
        Observable.interval(1, 10, TimeUnit.MINUTES).subscribe(aLong -> uploadAllPCM());
    }


    /**
     * 保存PCM信息到本地并且上传
     */
    public void savePCMData(File pcmFile, String gId, long pcmLength) {

        String src = pcmFile.getAbsolutePath();
        String target = src.replace(".pcm",".wav");
        try {
            Pcm2Wav.convertAudioFiles(src, target);
            FileUtil.deleteFile(src);
        } catch (Exception e) {
            e.printStackTrace();
        }
        TalkHistoryInfo talkHistoryInfo = new TalkHistoryInfo();
        talkHistoryInfo.setFileName(pcmFile.getName().replace(".pcm",".wav"));
        talkHistoryInfo.setFilePath(target);
        talkHistoryInfo.setStatus(0);
        talkHistoryInfo.setGroupID(gId);
        if (gId.contains("_")) {
            talkHistoryInfo.setTalkType("1");
        } else {
            talkHistoryInfo.setTalkType("0");
        }
        talkHistoryInfo.setUserID(UserManager.getInstance().getUserInfo().getUser_id());
        talkHistoryInfo.setUserName(UserManager.getInstance().getUserInfo().getName());
        SimpleDateFormat ft = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date(Long.parseLong(pcmFile.getName().replace(".pcm", "")));
        talkHistoryInfo.setTime("" + ft.format(date));
        talkHistoryInfo.setVoice_length(pcmLength);
        //上传状态
        talkHistoryInfo.setStatus(1);
        //设置上传时间
        talkHistoryInfo.setUploadTime(System.currentTimeMillis());
        DBEntityManager.saveTalkHistoryInfo(talkHistoryInfo);
        File file = new File(target);
        if (!file.exists()) {
            talkHistoryInfo.setStatus(3);
            DBEntityManager.saveTalkHistoryInfo(talkHistoryInfo);
        } else {
            uploadPCM(file, talkHistoryInfo.getUserID(), talkHistoryInfo.getGroupID());
        }

    }

    public void uploadAllPCM() {
        if (isUploadAll) {
            return;
        }
        isUploadAll = true;
        List<TalkHistoryInfo> talkHistoryInfos = DBEntityManager.getTalkHistoryInfos();
        if (talkHistoryInfos != null && talkHistoryInfos.size() > 0) {
            for (TalkHistoryInfo talkHistoryInfo : talkHistoryInfos) {
                String filePath = talkHistoryInfo.getFilePath();
                int status = talkHistoryInfo.getStatus();
                if (status == 1) {
                    //正在上传
                    long uploadTime = talkHistoryInfo.getUploadTime();
                    //超过10分钟 可能是上传失败了 但是状态没更新过来
                    if (System.currentTimeMillis() - uploadTime > 10 * 60 * 1000) {
                        status = 0;//状态变成为上传 在上传一次
                    }
                }

                if (status == 0) {
                    File file = new File(filePath);
                    if (!file.exists()) {
                        talkHistoryInfo.setStatus(3);
                        DBEntityManager.saveTalkHistoryInfo(talkHistoryInfo);
                        continue;
                    }
                    //上传状态
                    talkHistoryInfo.setStatus(1);
                    //设置上传时间
                    talkHistoryInfo.setUploadTime(System.currentTimeMillis());
                    DBEntityManager.saveTalkHistoryInfo(talkHistoryInfo);
                    uploadPCM(file, talkHistoryInfo.getUserID(), talkHistoryInfo.getGroupID());
                }

                if (status == 2) {
                    //上传完成
                    if (!talkHistoryInfo.getIsBindServer()) {
                        //绑定到服务器
                        requestUploadPCM(talkHistoryInfo);
                    }
                }
            }
        }
        isUploadAll = false;
    }

    private static String createPCMOssObjectKey(String keyName, String gid) {
        String dateFormat = new SimpleDateFormat("yyyy/MM/dd/HH").format(new Date());
        StringBuilder sb = new StringBuilder("pcm/");
        sb.append(dateFormat)
                .append("/")
                .append(gid)
                .append("/")
                .append(keyName);

        return sb.toString();
    }


    /**
     * 上传PCM到服务器
     */
    public void uploadPCM(File file, String uid, String gid) {

        QiNiuManager.getInstance().uploadPCM(file, createPCMOssObjectKey(uid + "_" + file.getName(), gid), (key, info, response) -> {
            TalkHistoryInfo talkHistoryInfo = DBEntityManager.getTalkHistoryInfo(file.getName());
            if (info != null && info.isOK()) {
                if (talkHistoryInfo != null) {
                    //上传成功
                    talkHistoryInfo.setStatus(2);
                    talkHistoryInfo.setVoice_url(key);
                    //绑定到服务器去
                    requestUploadPCM(talkHistoryInfo);
                }
            } else {
                //上传失败了
                if (talkHistoryInfo != null) {
                    //重新上传
                    talkHistoryInfo.setStatus(0);
                }
            }
            if (talkHistoryInfo != null) {
                DBEntityManager.saveTalkHistoryInfo(talkHistoryInfo);
            }
        });

    }


    /**
     * 下载PCM,具体回调怎么操作自己处理
     */
    public void downloadPCM(String voice_url, DownloadListener downloadListener) {
        String url = "http://onyyki115.bkt.clouddn.com/" + voice_url;
        String localPath = FileDownloadManager.getInstance().getLocalPathByUrl(voice_url);
        if (localPath != null) {
            downloadListener.onSuccess(localPath);
            return;
        }
        FileDownloadManager.getInstance().downloadVoice(voice_url, url, new FileDownloadSampleListener() {
            @Override
            protected void completed(BaseDownloadTask task) {
                downloadListener.onSuccess(task.getTargetFilePath());
            }

            @Override
            protected void error(BaseDownloadTask task, Throwable e) {
                downloadListener.onError(e);
            }

            @Override
            protected void progress(BaseDownloadTask task, int soFarBytes, int totalBytes) {
                super.progress(task, soFarBytes, totalBytes);
                Log.e(TAG, "soFarBytes>>"+soFarBytes+" totalBytes>>"+totalBytes);
                downloadListener.onProgress(soFarBytes*100/totalBytes);
            }
        });
    }

    /**
     * 下载PCM并且直接播放
     */
    public void downloadAndPlayPCM(String voice_url) {
        downloadPCM(voice_url, new DownloadListener() {
            @Override
            public void onSuccess(String voicePath) {
                playPCM(voicePath);
            }

            @Override
            public void onError(Throwable throwable) {
                ToastUtil.makeToast("获取语音失败,请重试");
            }

            @Override
            public void onProgress(int progress) {

            }
        });
    }


    public void playPCM(String path) {

        File file = new File(path);
        if (!file.exists()) {
            return;
        }

        int audioBufSize = AudioTrack.getMinBufferSize(8000,
                4,
                AudioFormat.ENCODING_PCM_16BIT);
        if (isPlay) {
            player.stop();
            player.release();
            player = null;
            isPlay = false;
        }

        if (player == null) {
            player = new AudioTrack(0, 8000,
                    AudioFormat.CHANNEL_OUT_MONO,
                    AudioFormat.ENCODING_PCM_16BIT,
                    audioBufSize,
                    AudioTrack.MODE_STREAM);
        }
        try {
            DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
            byte[] data = new byte[audioBufSize];
            player.play();//开始播放
            isPlay = true;
            while (isPlay) {
                int i = 0;
                try {
                    while (dis.available() > 0 && i < data.length) {
                        data[i] = dis.readByte();//录音时write Byte 那么读取时就该为readByte要相互对应
                        i++;

                    }
                } catch (IOException e) {
                    isPlay = false;
                    e.printStackTrace();
                }
                player.write(data, 0, data.length);
                if (i < audioBufSize) //表示读取完了
                {
                    player.stop();
                    break;
                }
            }
        } catch (Exception ignored) {
            ignored.printStackTrace();
            player.stop();//停止播放
        } finally {
            player.release();//释放资源
            player = null;
        }
        isPlay = false;
    }


    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMqttMessageEvent(MqttMessageEvent event) {
        if (CMDConstant.UPLOAD_TALK_HISTORY_RESP.equals(event.getMessage().getCmd())) {
            //语音上传
            JSONObject jsonObject = JSON.parseObject(event.getMessage().toString());
            String exerciseStr = jsonObject.getString("voice_url");//获取key为"_source"的值。
            DBEntityManager.updateTalkHistoryInfoBindServerByUrl(exerciseStr);
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMqttActionEvent(MQTTActionEvent event) {
        if (event.getStatus() == MqttConstant.MQTTStatusConstant.SUBSCRIBE_SUCCESS) {
            uploadAllPCM();
        }

    }

    /**
     * 上传PCM
     * @param
     */
    private void requestUploadPCM(TalkHistoryInfo talkHistoryInfo) {

        if (MQTTManager.getInstance().isConnected()) {
            Log.e(TAG, "requestUploadPCM>>"+BussinessBeanFactory.createUploadTalkHistory(talkHistoryInfo));
            Publication publication = PublishFactory.createPublication(BussinessBeanFactory.createUploadTalkHistory(talkHistoryInfo));
            MQTTManager.getInstance().publish(publication);
        }
    }

    public void release() {
        if (player != null) {
            player.stop();//停止播放
            player.release();
            player = null;
        }
    }


    public interface DownloadListener {
        public void onSuccess(String voicePath);

        public void onError(Throwable throwable);

        public void onProgress(int progress);
    }
}

